Allow only implementing Read::read_buf - #106643
Conversation
|
Hey! It looks like you've submitted a new PR for the library teams! If this PR contains changes to any Examples of
|
|
For a summary: This extends #[rustc_must_implement_one_of(read, read_buf)]
pub trait std::io::Read {
// (new)
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let mut buf = BorrowedBuf::from(buf);
self.read_buf(buf.unfilled()).map(|()| buf.len())
}
// (existing)
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {
default_read_buf(|b| self.read(b), buf)
}
}This does not make Whether or not we want to start using the r? @joshtriplett (who is on both relevant teams) Footnotes
|
|
I'm nominating this for T-lang to consider that question: are we OK with people using |
|
Separately, I'm nominating this for libs-api. Are we OK with (on nightly) allowing people to implement I am in favor, and in the absence of objections I'd r+ this once we have T-lang confirmation. |
|
Discussed this asynchronously with some T-lang folks, and one item that came up: we'd really like to see |
|
I've created a tracking issue: #107460 |
|
Removing I-libs-api-nominated for now, until the attribute has documentation in the reference. |
|
We discussed this once more in @rust-lang/lang, and confirmed that we have no objection to adding this on nightly. @bors r+ We'd consider it a blocker for stabilization of |
|
I am concerned about this negatively affecting the experience of non-nightly users. For example with this code: struct MyRead;
impl std::io::Read for MyRead {}current stable gives you this error: error[E0046]: not all trait items implemented, missing: `read`
--> src/main.rs:3:1
|
3 | impl std::io::Read for MyRead {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `read` in implementation
|
= help: implement the missing item: `fn read(&mut self, _: &mut [u8]) -> Result<usize, std::io::Error> { todo!() }`whereas rustc built from this PR gives this error: error[E0046]: not all trait items implemented, missing one of: `read`, `read_buf`
--> src/main.rs:3:1
|
3 | impl std::io::Read for MyRead {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing one of `read`, `read_buf` in implementation
|
note: required because of this annotation
--> /git/rust/library/std/src/io/mod.rs:552:1
|
552 | #[rustc_must_implement_one_of(read, read_buf)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Some concerns:
@bors r- |
Valid; I agree that we should avoid suggesting implementing a method that you can't implement. @WaffleLapkin, would that be feasible, and can you add a test verifying that behavior as well?
Fair. That seems like a reasonable solution for the common case. |
@dtolnay thanks for rising these concerns! My guess is that r-a will not autofill any methods, as they all have default bodies. I'll look into how we can support this feature in r-a.
@joshtriplett This should be feasible. I'll make a PR that removes mentions of unstable methods from this diagnostic and shows the signatures soon™. For now, marking this PR as blocked. |
|
@WaffleLapkin I needed to update it in order to test it with #160106 anyway. I don't think we necessarily need to block on improving the rust-analyzer suggestions here. I think with the improved suggestions (now merged), and if I add support for not suggesting unstable methods (in progress), that would largely solve the problem. We can ping the rust-analyzer folks and ask them to look at updating that asynchronously. |
|
I've now submitted #160250 . With that change together with #160106 , the suggestions now show the signatures for I would propose that once #160250 goes in we unblock and merge this PR. Separately: cc @rust-lang/rust-analyzer to request support for handling and testing suggestions from |
IIUC, we should suggest implementing either one of |
Sounds roughly right. |
|
Status:
As a result, I think we can now go ahead with this PR. |
|
@bors r+ rollup |
|
I have another concern about the implementation. Given that unlike The current implementation does the easy thing and returns the error, but I think that dropping some bytes of the reader is the wrong thing to do. On the contrary, swallowing the error is more likely to be OK, since if it was an important error it is more likely to be returned too in the next call. |
…htriplett Allow only implementing `Read::read_buf` This PR allows users to only implement `Read::read_buf`, without the need for implementing `Read::read`. `rustc_must_implement_one_of` annotation ensures that **at least** one of the methods is implemented, so that the default impls don't create infinite recursion. Note that `Read::read_buf` is unstable, so this doesn't change anything on stable, there you still need to implement `Read::read`, since you can't implement `Read::read_buf`. Thus, we don't expose `rustc_must_implement_one_of` to stable. r? @thomcc
|
@a1phyr You raised that on the tracking issue for |
Rollup of 6 pull requests Successful merges: - #159844 (Subtree cg_gcc sync (2026-07-24)) - #156527 (Move `std::io` tests to `alloctests` & add prelude) - #159525 (Stabilize passing 128-bit integers via vector registers with `asm!` on x86) - #160342 (Specialize `advance_by` method of `Fuse`) - #106643 (Allow only implementing `Read::read_buf`) - #159729 (allocations are allowed to grow (but not shrink))
|
I'm curious, can this also be used for |
|
Also, @joshtriplett but also others, as a member of T-rust-analyzer it will help us if the code will mark the "preferred" method to implement in case none are (for quickfixes like "add missing impl members"). It can come in the form of a separate attribute (perhaps under the |
…htriplett Allow only implementing `Read::read_buf` This PR allows users to only implement `Read::read_buf`, without the need for implementing `Read::read`. `rustc_must_implement_one_of` annotation ensures that **at least** one of the methods is implemented, so that the default impls don't create infinite recursion. Note that `Read::read_buf` is unstable, so this doesn't change anything on stable, there you still need to implement `Read::read`, since you can't implement `Read::read_buf`. Thus, we don't expose `rustc_must_implement_one_of` to stable. r? @thomcc
Rollup of 6 pull requests Successful merges: - #156527 (Move `std::io` tests to `alloctests` & add prelude) - #159525 (Stabilize passing 128-bit integers via vector registers with `asm!` on x86) - #160342 (Specialize `advance_by` method of `Fuse`) - #106643 (Allow only implementing `Read::read_buf`) - #159729 (allocations are allowed to grow (but not shrink)) - #159881 (fix: Do not stop `visible_parent_map` breadth-first search reaching children of `#[doc(hidden)]` modules)
…htriplett Allow only implementing `Read::read_buf` This PR allows users to only implement `Read::read_buf`, without the need for implementing `Read::read`. `rustc_must_implement_one_of` annotation ensures that **at least** one of the methods is implemented, so that the default impls don't create infinite recursion. Note that `Read::read_buf` is unstable, so this doesn't change anything on stable, there you still need to implement `Read::read`, since you can't implement `Read::read_buf`. Thus, we don't expose `rustc_must_implement_one_of` to stable. r? @thomcc
…uwer Rollup of 12 pull requests Successful merges: - #159906 (Semantic check of `mut` restrictions) - #156527 (Move `std::io` tests to `alloctests` & add prelude) - #159525 (Stabilize passing 128-bit integers via vector registers with `asm!` on x86) - #160342 (Specialize `advance_by` method of `Fuse`) - #160358 (borrowck: Simplify deps to build compiler 30s faster) - #160375 (miri subtree update) - #106643 (Allow only implementing `Read::read_buf`) - #159499 (tests: prefer max-llvm-major-version over open LLVM ranges) - #159729 (allocations are allowed to grow (but not shrink)) - #159881 (fix: Do not stop `visible_parent_map` breadth-first search reaching children of `#[doc(hidden)]` modules) - #160189 (Move codegen_stmt_debuginfo to debuginfo.rs) - #160356 (Add more tests for `must_implement_one_of`)
Rollup merge of #106643 - WaffleLapkin:read_recursive, r=joshtriplett Allow only implementing `Read::read_buf` This PR allows users to only implement `Read::read_buf`, without the need for implementing `Read::read`. `rustc_must_implement_one_of` annotation ensures that **at least** one of the methods is implemented, so that the default impls don't create infinite recursion. Note that `Read::read_buf` is unstable, so this doesn't change anything on stable, there you still need to implement `Read::read`, since you can't implement `Read::read_buf`. Thus, we don't expose `rustc_must_implement_one_of` to stable. r? @thomcc
View all comments
This PR allows users to only implement
Read::read_buf, without the need for implementingRead::read.rustc_must_implement_one_ofannotation ensures that at least one of the methods is implemented, so that the default impls don't create infinite recursion.Note that
Read::read_bufis unstable, so this doesn't change anything on stable, there you still need to implementRead::read, since you can't implementRead::read_buf. Thus, we don't exposerustc_must_implement_one_ofto stable.r? @thomcc